Skip to content

PSwap Contract#2636

Draft
VAIBHAVJINDAL3012 wants to merge 6 commits into0xMiden:nextfrom
inicio-labs:pswap-note
Draft

PSwap Contract#2636
VAIBHAVJINDAL3012 wants to merge 6 commits into0xMiden:nextfrom
inicio-labs:pswap-note

Conversation

@VAIBHAVJINDAL3012
Copy link

  • Add PSWAP (partially-fillable swap) note to miden-standards — a new note script that enables partial
    fills, creator reclaim, and inflight cross-swaps for decentralized asset exchange

    • MASM script (pswap.masm) uses 18-item KEY+VALUE storage layout, proportional price calculation with
      1e5 precision factor, and an early-return optimization for full fills to avoid integer truncation
    • Rust library (PswapNote) provides note creation, output note construction (P2ID payback + optional
      remainder), storage parsing, and calculate_offered_for_requested convenience method
    • 12 integration tests covering full fill, private fill, partial fill, inflight cross-swap, creator
      reclaim, invalid input rejection, multiple fill amounts, non-exact ratios, fuzz cases, and chained
      partial fills

    Test plan

    • cargo build -p miden-standards — MASM compiles into standards library
    • cargo test -p miden-standards pswap — 4 unit tests (script loading, tag construction, output
      calculation, storage parsing)
    • cargo test -p miden-testing pswap — 12 integration tests (full/partial/private fills, cross-swaps,
      reclaim, fuzz, chained fills)

/// - Note can be partially or fully filled by consumers
/// - Unfilled portions create remainder notes
/// - Creator receives requested assets via P2ID notes
pub struct PswapNote;
Copy link
Contributor

@PhilippGackstatter PhilippGackstatter Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're adding this as a completely new note, it would be great if we could immediately set it up with the structure we want to end up with, i.e. the one described in #2283.

So roughly:

pub struct PswapNoteStorage {
    requested_key: Word,
    requested_value: Word,
    swapp_tag: NoteTag,
    p2id_tag: NoteTag,
    swap_count: u64,
    creator_account_id: AccountId,
}

impl PswapNoteStorage {
    pub fn into_recipient(self, serial_num: Word) -> NoteRecipient {
        todo!()
    }
}

impl From<PswapNoteStorage> for NoteStorage {
    fn from(pswap_storage: PswapNoteStorage) -> Self {
        todo!()
    }
}

#[derive(Debug, Clone, bon::Builder)]
#[builder(finish_fn(vis = "", name = build_internal))]
pub struct PswapNote {
    sender: AccountId,

    storage: PswapNoteStorage,

    serial_number: Word,

    #[builder(default = NoteType::Private)]
    note_type: NoteType,

    #[builder(default)]
    assets: NoteAssets,

    #[builder(default)]
    attachment: NoteAttachment,
}

impl PswapNote {
    pub fn execute(
        &self,
        consumer_account_id: AccountId,
        input_amount: u64,
        inflight_amount: u64,
    ) -> Result<(Note, Option<PswapNote>), NoteError> {
        todo!("what create_output_notes does now")
    }
}

This would result in a more natural API, i.e. execute takes &self instead of create_output_notes taking an arbitrary &Note.

What do you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agree to this.
I have made the change.

Vaibhav Jindal added 5 commits March 20, 2026 09:06
…MS, remove create_ wrappers, add builder finish_fn

- Rename swapp_tag -> pswap_tag and SWAPp -> PSWAP throughout
- Rename NUM_ITEMS -> NUM_STORAGE_ITEMS for clarity
- Remove create_p2id_payback_note and create_remainder_note wrappers,
  make build_ functions public instead
- Compute p2id_tag inside build_p2id_payback_note from self.storage
- Add #[builder(finish_fn(vis = "", name = build_internal))] to PswapNote
…ctly

Replace all test helper wrappers with direct calls to library functions:
- create_pswap_note -> PswapNote::create()
- create_expected_pswap_p2id_note + create_expected_pswap_remainder_note -> pswap.execute()
- build_pswap_storage -> PswapNoteStorage::from_parts()
- Remove make_pswap_tag, make_note_assets, make_note_args, compute_p2id_tag_*
- Inline calculate_output_amount as PswapNote::calculate_output_amount()
- Replace storage layout list with markdown table
- Remove trivial "Returns the X" docs on simple getters
- Add # Errors sections where relevant
- Rewrite method docs to describe intent, not implementation
- Add one-line docs on From/TryFrom conversion impls
- Tighten PswapNote struct doc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants